#include "thread.h"

#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>

#include "reactor.h"
#include "controller.h"
/*
池化技术，就是对资源的复用
线程池-对线程的复用
进程池-对进程的复用
内存池、对象池、连接池，，，，，
*/

Thread::Thread() {
    if ( pthread_create(&m_tid, NULL, taskFunc, this) ) {
        LOG_ERROR << "create thread failed!";
    }

    if (-1 == socketpair(AF_UNIX, SOCK_STREAM, 0, m_channel)) {
        LOG_ERROR << strerror(errno);
    }
}

Thread::~Thread() {
    pthread_join(m_tid, NULL);
}

int Thread::GetSocketPairFirst() const {
    return m_channel[0];
}

int Thread::GetSocketPairSecond() const {
    return m_channel[1];
}

pthread_t Thread::GetTid() const {
    return m_tid;
}


//one loop per thread 
//reactor是抽象的模式;   muduo、libevent等是对抽象reactor的一种实现，是具体的。
void* Thread::taskFunc(void* arg) {
    Thread* thread = static_cast<Thread*>(arg);
    thread->m_reactor = new Reactor();
    thread->m_ctroller = new Controller();
    thread->m_reactor->AddEventAndHander(thread->GetSocketPairSecond(), EV_READ | EV_PERSIST, Thread::SocketPairEventCallBack, arg);
    LOG_INFO << thread->GetTid();
    thread->m_reactor->Loop();  //开启线程上的loop循环    
    return NULL;
} 

//第一个参数int fd就是thread->GetSocketPairSecond()。这是与主线程的管道
void Thread::SocketPairEventCallBack(int fd, short events, void* arg) {
    Thread* thread = static_cast<Thread*>(arg);
    int cfd = 0;    //<存放主线程发过来的，建立连接的文件描述符。就是与客户端建立好的连接。
    if (read(fd, &cfd, 4) <= 0) {
        LOG_ERROR << strerror(errno);
    }

    //接下来就是处理客户端上发生的事件  Client
    thread->m_reactor->AddEventAndHander(cfd, EV_READ | EV_PERSIST, Thread::ClientIOEventCallBack, arg);
}

void Thread::ClientIOEventCallBack(int fd, short events, void* arg) {
    Thread* thread = static_cast<Thread*>(arg);
    char buf[LARGE_BUF_LEN] = {0};
    if ( read(fd, buf, LARGE_BUF_LEN) <= 0) {
        LOG_INFO << "client disconneted!";
        //读到的数据<0就是断开了连接
    }
    LOG_INFO << buf;

    std::string data = buf;
    thread->m_ctroller->process(fd, data);
    // decode + compute + encode
    // mvc + myql + redis
    // 最后一句就是开始处理业务
}